package com.atguigu.gmall.cart.service;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.feign.GmallPmsClient;
import com.atguigu.gmall.cart.feign.GmallSmsClient;
import com.atguigu.gmall.cart.feign.GmallWmsClient;
import com.atguigu.gmall.cart.intercept.LoginInterceptor;
import com.atguigu.gmall.cart.mapper.CartMapper;
import com.atguigu.gmall.cart.pojo.Cart;
import com.atguigu.gmall.cart.pojo.UserInfo;
import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.common.exception.CartException;
import com.atguigu.gmall.pms.entity.SkuAttrValueEntity;
import com.atguigu.gmall.pms.entity.SkuEntity;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.atguigu.sms.vo.ItemSaleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: xie.zh
 * @create: 2021.03.30   15:50
 * @version: 1.0
 */
@Service
public class CartService {

    @Autowired
    private CartAsyncService cartAsyncService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private GmallPmsClient pmsClient;
    @Autowired
    private GmallSmsClient smsClient;
    @Autowired
    private GmallWmsClient wmsClient;

    private static final String KEY_PREFIX = "cart:info:";
    private static final String PRICE_PREFIX = "cart:price:";

    public void saveCart(Cart cart) {
        String userId = getUserId();
        String key = KEY_PREFIX + userId;
        String skuIdString = cart.getSkuId().toString();
        BigDecimal count = cart.getCount();
        //2、判断当前用户的购物车中是否包含该记录
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);
        if (hashOps.hasKey(cart.getSkuId().toString())) {
            //包含 更新数量
            String json = hashOps.get(skuIdString).toString();
            cart = JSON.parseObject(json, Cart.class);
            //数量累加
            cart.setCount(cart.getCount().add(count));
            //更新后数量的cart写入redis和mysql
            this.cartAsyncService.updateCart(userId, cart, skuIdString);
        } else {
            //不包含 新增记录
            cart.setCheck(true);
            cart.setUserId(userId);
            ResponseVo<SkuEntity> skuEntityResponseVo = pmsClient.querySkuById(cart.getSkuId());
            SkuEntity skuEntity = skuEntityResponseVo.getData();
            if (skuEntity == null) {
                throw new CartException("您加入购物车的商品不存在！");
            }
            //sku信息
            cart.setTitle(skuEntity.getTitle());
            cart.setPrice(skuEntity.getPrice());
            cart.setDefaultImage(skuEntity.getDefaultImage());

            //销售属性
            ResponseVo<List<SkuAttrValueEntity>> saleAttrsResponseVo = this.pmsClient.querySkuAttrValueBySkuId(cart.getSkuId());
            List<SkuAttrValueEntity> attrValueEntities = saleAttrsResponseVo.getData();
            cart.setSaleAttrs(JSON.toJSONString(attrValueEntities));

            //库存
            ResponseVo<List<WareSkuEntity>> wareResponseVo = this.wmsClient.queryWareSkuBySkuId(cart.getSkuId());
            List<WareSkuEntity> wareSkuEntities = wareResponseVo.getData();
            if (!CollectionUtils.isEmpty(wareSkuEntities)) {
                cart.setStore(wareSkuEntities.stream().anyMatch(wareSkuEntity -> wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() > 0));
            }
            //营销信息
            ResponseVo<List<ItemSaleVo>> salesResponseVo = this.smsClient.querySalesBySkuId(cart.getSkuId());
            List<ItemSaleVo> itemSaleVos = salesResponseVo.getData();
            cart.setSales(JSON.toJSONString(itemSaleVos));

            this.cartAsyncService.insertCart(userId, cart);
            this.redisTemplate.opsForValue().set(PRICE_PREFIX + skuIdString, skuEntity.getPrice().toString());
        }
        hashOps.put(skuIdString, JSON.toJSONString(cart));
    }

    private String getUserId() {
        //1、获取登录状态
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        String userId = "";

        if (userInfo.getUserId() != null) {
            userId += userInfo.getUserId();
        } else {
            userId += userInfo.getUserKey();
        }
        return userId;
    }

    public Cart quryCartBySkuId(Long skuId, Integer count) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        if (hashOps.hasKey(skuId.toString())) {
            String json = hashOps.get(skuId.toString()).toString();
            Cart cart = JSON.parseObject(json, Cart.class);
            cart.setCount(new BigDecimal(count));
            return cart;
        } else {
            throw new CartException("当前用户不包含该购物记录");
        }
    }

    public List<Cart> queryCarts() {
        //查询未登录购物车
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        String userKey = userInfo.getUserKey();
        BoundHashOperations<String, Object, Object> unLoginMap = this.redisTemplate.boundHashOps(KEY_PREFIX + userKey);
        List<Object> unLoginCartJsons = unLoginMap.values();
        List<Cart> unLoginCarts = null;
        if (!CollectionUtils.isEmpty(unLoginCartJsons)) {
            unLoginCarts = unLoginCartJsons.stream().map(cartJson -> {
                Cart cart = JSON.parseObject(cartJson.toString(), Cart.class);
                cart.setCurrentPrice(new BigDecimal(this.redisTemplate.opsForValue().get(PRICE_PREFIX + cart.getSkuId())));
                return cart;
            }).collect(Collectors.toList());
        }
        //是否登录 未登录则返回未登录购物车
        Long userId = userInfo.getUserId();
        if (userId == null) {
            return unLoginCarts;
        }
        //登录状态下 合并未登录购物车到登录状态购物车
        BoundHashOperations<String, Object, Object> loginMap = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        if (!CollectionUtils.isEmpty(unLoginCarts)) {
            unLoginCarts.forEach(unLoginCart -> {
                String skuIdString = unLoginCart.getSkuId().toString();
                BigDecimal count = unLoginCart.getCount();
                if (loginMap.hasKey(skuIdString)) {
                    String loginCartJson = loginMap.get(skuIdString).toString();
                    unLoginCart = JSON.parseObject(loginCartJson, Cart.class);
                    unLoginCart.setCount(count.add(unLoginCart.getCount()));
                    //保存到redis 并同步到mysql
                    this.cartAsyncService.updateCart(userId.toString(), unLoginCart, skuIdString);
                } else {
                    //不包含 则新增一条记录
                    unLoginCart.setUserId(userId.toString());
                    this.cartAsyncService.insertCart(userId.toString(), unLoginCart);
                }
                loginMap.put(skuIdString, JSON.toJSONString(unLoginCart));
            });
            //删除未登录购物车
            this.redisTemplate.delete(KEY_PREFIX + userKey);
            this.cartAsyncService.deleteCartByUserId(userKey);
        }
        //返回登录状态下的购物车
        List<Object> loginCartJsons = loginMap.values();
        if (!CollectionUtils.isEmpty(loginCartJsons)) {
            return loginCartJsons.stream().map(cartJson -> {
                Cart cart = JSON.parseObject(cartJson.toString(), Cart.class);
                cart.setCurrentPrice(new BigDecimal(this.redisTemplate.opsForValue().get(PRICE_PREFIX + cart.getSkuId())));
                return cart;
            }).collect(Collectors.toList());
        }
        return null;
    }

    public void updateNum(Cart cart) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        String skuIdString = cart.getSkuId().toString();
        if (hashOps.hasKey(skuIdString)) {
            BigDecimal count = cart.getCount();
            String cartJson = hashOps.get(skuIdString).toString();
            cart = JSON.parseObject(cartJson, Cart.class);
            cart.setCount(count);
            hashOps.put(skuIdString, JSON.toJSONString(cart));
            this.cartAsyncService.updateCart(userId, cart, skuIdString);
            return;
        }
        throw new CartException("该用户购物车不包含该记录");
    }

    public void updateStatus(Cart cart) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        String skuIdString = cart.getSkuId().toString();
        if (hashOps.hasKey(skuIdString)) {
            Boolean check = cart.getCheck();
            String cartJson = hashOps.get(skuIdString).toString();
            cart = JSON.parseObject(cartJson, Cart.class);
            cart.setCheck(check);
            hashOps.put(skuIdString, JSON.toJSONString(cart));
            this.cartAsyncService.updateCart(userId, cart, skuIdString);
            return;
        }
        throw new CartException("该用户购物车不包含该记录");
    }

    public void deleteCart(Long skuId) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        hashOps.delete(skuId.toString());
        this.cartAsyncService.deleteCartByUserIdAndSkuId(userId, skuId);
    }

    public List<Cart> queryUserCartWithCheck(Long userId) {
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        List<Object> cartJsons = hashOps.values();
        if (!CollectionUtils.isEmpty(cartJsons)) {
            return cartJsons.stream().map(cartJson -> JSON.parseObject(cartJson.toString(), Cart.class))
                    .filter(Cart::getCheck).collect(Collectors.toList());
        }
        return null;
    }
}
